"""
    一、
        明确需要爬取那些视频
        视频地址：https://space.bilibili.com/533996453/video
    二、
        进行抓包，查看数据在哪里
        数据包地址：https://www.bilibili.com/video/BV19w4m1U79H/?spm_id_from=333.999.0.0
    三、
        发送请求，获取数据包，进行解析
    四、
        保存数据
        注意：
            bilibili视频是音频和视频分开的，需要合并
    五、
        视频地址
        https://www.bilibili.com/video/BV1Ei421S7s6/?spm_id_from=333.999.0.0
        https://www.bilibili.com/video/BV1Js421G7wN/?spm_id_from=333.999.0.0
        https://www.bilibili.com/video/BV1qt421T7Qe/?spm_id_from=333.999.0.0
        改变的只有BV~~，只要拿到BV就可以爬取
"""

import re
import json
import time
import requests
from DrissionPage import ChromiumPage
from moviepy.editor import VideoFileClip, AudioFileClip, CompositeVideoClip

# 请求函数
def get_json(url):
    header = {
        "Accept": "*/*",
        "Accept-Encoding": "gzip, deflate, br, zstd",
        "Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6",
        "Cache-Control": "no-cache",
        "Content-Length": "542",
        "Content-Type": "text/plain",
        "Cookie": "buvid3=4F9BDBB2-E32C-54A1-17BE-544D7864C79950191infoc; b_nut=1716169750; _uuid=CA95F4AE-4104C-101BD-D5E10-FC181231B8B848604infoc; enable_web_push=DISABLE; home_feed_column=5; browser_resolution=1536-754; CURRENT_FNVAL=4048; rpdid=|(k|k~~~l||m0J'u~uYuYm~~J; DedeUserID=506537472; DedeUserID__ckMd5=6f456d991619f8ed; header_theme_version=CLOSE; PVID=2; buvid_fp_plain=undefined; buvid4=FA92A1B7-B3A5-A3F7-F9CD-EAA83BDF549E54633-024052001-GnYf1Ob1%2FD3FS4QArMQ5cw%3D%3D; b_lsid=24C273AF_18FEB72446B; bsource=search_bing; SESSDATA=944e13fc%2C1733194094%2C20fbb%2A62CjDPWw096wKwfdhL62oGl7XS9WXGjKC7ba_M2koDTLF6unVqF6YQMbknWUxmoITB0jgSVmNqX196UU14MDJWMDRMZFNWN01Qc0M1UU5IaTE0dmZ4bFR0NUd1M1lDQ2F2b0tlc0daUnFSR3FFN2pHOVVkMnhuQmsxb2ZfRlNWQUxXeGVqaTlQc3dnIIEC; bili_jct=16df257c38fb422ef5fcd7b6bfbc1e41; sid=7w5b2to6; bili_ticket=eyJhbGciOiJIUzI1NiIsImtpZCI6InMwMyIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MTc5MDEzMDYsImlhdCI6MTcxNzY0MjA0NiwicGx0IjotMX0.FrgPXyPP7tRTP_jjs4rwYnjkv5rd8HC8X3eWHxhuiHg; bili_ticket_expires=1717901246; fingerprint=6a38d87a84a696bf79f5b24a8ad86dab; buvid_fp=4F9BDBB2-E32C-54A1-17BE-544D7864C79950191infoc",
        "Origin": "https://www.bilibili.com",
        "Pragma": "no-cache",
        "Priority": "u=1, i",
        "Referer": "https://www.bilibili.com/video/BV1nJ4m1w7KN/?spm_id_from=333.1007.tianma.1-2-2.click&vd_source=5279f488b5ef525ebf503e2dddd079bf",
        "Sec-Ch-Ua": "\"Microsoft Edge\";v=\"125\", \"Chromium\";v=\"125\", \"Not.A/Brand\";v=\"24\"",
        "Sec-Ch-Ua-Mobile": "?0",
        "Sec-Ch-Ua-Platform": "\"Windows\"",
        "Sec-Fetch-Dest": "empty",
        "Sec-Fetch-Mode": "cors",
        "Sec-Fetch-Site": "same-site",
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36 Edg/125.0.0.0"
    }
    try:
        time.sleep(3)
        response = requests.get(url=url, headers=header)
        response.raise_for_status()
        response.encoding = response.apparent_encoding
        return response
    except Exception as e:
        print(e)
        return None

# 解析函数
def get_parse(title_list, BVid):
    response = get_json(url=f'https://www.bilibili.com/video/{BVid}/?spm_id_from=333.999.0.0')
    if response:
        # 标题，不能有空格和特殊字符
        title = re.findall('<title data-vue-meta="true">(.*?)哔哩哔哩_bilibili</title>', response.text)[0]
        title = re.findall('[\u4e00-\u9fff]+', title)
        title = ''.join(title)
        # 获取音频和视频
        info = json.loads(re.findall('<script>window.__playinfo__=(.*?)</script>', response.text)[0])
        video_url = info['data']['dash']['video'][0]['baseUrl']
        audio_url = info['data']['dash']['audio'][0]['baseUrl']
        title_list.append(title)
        save_file(title, video_url, audio_url)
    else:
        print('解析失败')

# 保存函数
def save_file(title, video_url, audio_url):
    # 获取音视频二进制文件
    video_content = get_json(url=video_url).content
    audio_content = get_json(url=audio_url).content
    # 保存音视频文件
    with open('E:\\python-learn\\爬虫项目\\bilibili\\' + title + '.mp4', 'wb') as video:
        video.write(video_content)
    with open('E:\\python-learn\\爬虫项目\\bilibili\\' + title + '.mp3', 'wb') as audio:
        audio.write(audio_content)

# 音视频合并函数
def mergeVideoAudio(title_list):
    # 加载视频和音频文件
    for title in title_list:
        video_clip = VideoFileClip(f'./bilibili/{title}.mp4')
        audio_clip = AudioFileClip(f'./bilibili/{title}.mp3')

        # 设置音频和视频的长度一致（取两者中较短的一个）
        final_duration = min(video_clip.duration, audio_clip.duration)
        video_clip = video_clip.set_duration(final_duration)
        audio_clip = audio_clip.set_duration(final_duration)

        # 合并视频和音频
        final_clip = CompositeVideoClip([video_clip.set_audio(audio_clip)])

        # 输出文件路径
        output_file = f'./bilibili/video/{title}.mp4'
        # 写入输出文件
        final_clip.write_videofile(output_file, codec='libx264', audio_codec='aac')

if __name__ == '__main__':
    # 存放视频标题
    title_list = []

    # 创建页面对象
    page = ChromiumPage()
    # 监听数据包
    page.listen.start('api.bilibili.com/x/space/wbi/arc/search')
    try:
        # 访问请求
        page.get(url='https://space.bilibili.com/533996453/video')
        # 获取前2页视频
        for i in range(1, 3):
            # 等待加载
            resp = page.listen.wait()
            # 获取数据包
            json_data = resp.response.body
            # 获取每个作品的BV号
            for bvid in json_data['data']['list']['vlist']:
                BVid = bvid['bvid']
                # 调用解析函数
                get_parse(title_list, BVid)
            time.sleep(3)
            # 翻页
            page.ele('x://div[@id="submit-video"]/div/div//ul[@class="be-pager"]//li[@class="be-pager-next"]').click()
    except Exception as e:
        print(e)
    finally:
        page.quit()
    # 调用合并函数
    mergeVideoAudio(title_list)